package com.dwms.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.dwms.constant.HeaderConstants;
import com.dwms.entity.Request;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Objects;

@Slf4j
public class WebUtil {
    
    private final static int PORT = 80;

    /**
     * 获取上下文URL全路径
     */
    public static String getContextPath(HttpServletRequest request) {
        StringBuilder sb = new StringBuilder();
        sb.append(request.getScheme()).append("://");
        sb.append(request.getServerName());
        //80端口无需拼接
        if (request.getServerPort() != PORT) {
            sb.append(":").append(request.getServerPort());
        }
        sb.append(request.getContextPath());
        return sb.toString();
    }

    /**
     * 获取IP地址
     * 使用Nginx等反向代理软件， 则不能通过request.getRemoteAddr()获取IP地址
     * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，X-Forwarded-For中第一个非unknown的有效IP字符串，则为真实IP地址
     *
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StrUtil.isEmpty(ip) || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }

    /**
     * 输出响应信息
     */
    public static void outPrint(HttpServletResponse response, String result) {
        response.setContentType("application/json; charset=utf-8");
        response.setCharacterEncoding("UTF-8");
        try {
            PrintWriter pw = response.getWriter();
            pw.write(result);
            pw.flush();
            pw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取管理端请求头参数
     **/
    public static Request getAdminRequest(HttpServletRequest httpServletReq, Request request) {
        setRequest(request, getHeaderMap(httpServletReq));
        return request;
    }

    /**
     * 设置请求头参数
    
     */
    public static void setRequest(Request request, Map<String, String> headerMap) {
        request = request == null ? new Request() : request;
        request.setSource(headerMap.get(HeaderConstants.SOURCE));
        request.setTimestamp(headerMap.get(HeaderConstants.TIME_STAMP));
        request.setDeviceIp(headerMap.get(HeaderConstants.DEVICE_IP));
        request.setLoginToken(headerMap.get(HeaderConstants.LOGIN_TOKEN));
        request.setSign(headerMap.get(HeaderConstants.SIGN));
        request.setSessionGenerateId(headerMap.get(HeaderConstants.SESSION_GENERATE_ID));
        request.setRandomId(headerMap.get(HeaderConstants.RANDOM_ID));
        request.setUri(headerMap.get(HeaderConstants.URI));
    }


    /**
     * 获取请求头的数据
     **/
    public static Map<String, String> getHeaderMap(HttpServletRequest httpServletReq) {
        String source = httpServletReq.getHeader(HeaderConstants.SOURCE);
        String loginToken = httpServletReq.getHeader(HeaderConstants.LOGIN_TOKEN);
        String sign = httpServletReq.getHeader(HeaderConstants.SIGN);
        String sessionGenerateId = httpServletReq.getHeader(HeaderConstants.SESSION_GENERATE_ID);
        String uri = httpServletReq.getHeader(HeaderConstants.URI);
        String randomId = httpServletReq.getHeader(HeaderConstants.RANDOM_ID);
        String timestamp = httpServletReq.getHeader(HeaderConstants.TIME_STAMP);
        String deviceIp = httpServletReq.getHeader(HeaderConstants.DEVICE_IP);
        Request request = new Request();
        request.setSource(source);
        request.setTimestamp(timestamp);
        request.setDeviceIp(StrUtil.isEmpty(deviceIp) ? getIpAddr(httpServletReq) : deviceIp);
        request.setLoginToken(loginToken);
        request.setSign(sign);
        request.setSessionGenerateId(sessionGenerateId);
        request.setRandomId(randomId);
        request.setUri(uri);
        Map<String, Object> headersMap = BeanUtil.beanToMap(request);
        if (Objects.isNull(headersMap)) {
            return Maps.newHashMap();
        }
        Map<String, String> headerMap = Maps.newHashMap();
        for (Map.Entry<String, Object> entry : headersMap.entrySet()) {
            if (entry.getValue() != null) {
                headerMap.put(entry.getKey(), entry.getValue().toString());
            }
        }
        headerMap.put("accessToken", loginToken);
        return headerMap;
    }
}
